export = {}
/** ts里,this是个参数*/
/*function xxx(){
  console.log(this); //TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
}*/

interface Human {
  name: string;
  age: number;
}

function fn(this: Human) {
  console.log(this);
}

// fn({name: 'ahhh', age: 123}); // TS2554: Expected 0 arguments, but got 1.
/**↑
typescript 中 this是被当做参数的
,参数里的this很特殊
,它不被当做argument
,故上面会报错
*/

//我们可以通过call、apply调用fn时指定this
fn.call({name: 'ahhh', age: 123});
fn.call(123); //TS2345: Argument of type 'number' is not assignable to parameter of type 'Human'.

const obj = {
  fn
  // ,name:''
  // ,age:123
};
obj.fn(); //谁“点”函数 函数里的this就是谁
/** ↑
 TS2684: The 'this' context of type '{ fn: (this: Human) => void; }' is not assignable to method's 'this' of type 'Human'.
 Type '{ fn: (this: Human) => void; }' is missing the following properties from type 'Human': name, age*/



/** 使用typeof自动提取类型 (提一嘴, type有类型提升的功能)*/
let obj2 = {a:1,b:'fawf'};
type IThis = typeof obj2; // {a: number, b: string}
function fnY(this:IThis){
  console.log(this);
}
fnY.call(obj2);



/** ↓如果我们期望 this传递的时候要限制类型,但也允许不传递this呢？*/
function fnX(this: Human|void) {
  console.log(this);
}

fnX();




/** 为什么将this当做参数*/
//之所以 typescript里 将this当做参数
//是因为像js一样的话 一眼很难看出this到底是什么↓↓
// function fn1() {
//   console.log(this);
//   function fn2(){
//     console.log(this);
//   }
//   fn2(); // window or undefined
// }
// fn1.call({name:'ahhh'})


//但改成ts后：
function fn1(this:any) {
  console.log(this);
  function fn2(this:any){
    console.log(this);
  }
  fn2(); // ← 没传this参数 不就是undefined吗(or window ←这是js遗留问题)
}
fn1.call({name: 'ahhh'});
